/*
@author: Shizuku
@file: scshopping.go
@time: 2022/11/18 11:47
*/
package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strconv"
)
//存放商品信息
//{"F001": {"name": "apple", "price":"9"},
//"F002": {"name": "banana", "price": "3"}}
var products = map[string]map[string]string{
	"F001": {"name": "apple", "price":"9"},
	"F002": {"name": "banana", "price": "3"},
	"F003": {"name": "orange", "price": "4"}}

//存放用户信息 {"sc": {"passwd": "123456", "money": 300}}
//var user map[string]map[string]interface{} --> 直接声明map，没有赋值，指向的是nil
var user = make(map[string]map[string]string)
//购物车信息文件	car={"sc": {"item": "apple", "qty": "3", "expense": qty * price}}
var car = make(map[string]map[string]string)
//声明用户信息文件
var user_file string = "user.txt"
//声明购物车信息文件
var shoppingcar_file string = "shoppingcar.txt"

func main() {
	//执行用户信息初始化函数
	init_user(user_file)
	fmt.Println("***欢迎进入三乐购物系统***")
	for {
		fmt.Println("请输入选项：\n1、登录\n2、注册")
		var option string
		fmt.Scan(&option)
		switch option {
		case "1":
			var name string
			var passwd string
			fmt.Print("请输入用户名：")
			fmt.Scan(&name)
			fmt.Print("请输入密码：")
			fmt.Scan(&passwd)
			if login(name, passwd){
				fmt.Println("登陆成功！")
				flag := true
				for flag{
					flag = false
					menu()
					var op string
					fmt.Scan(&op)
					switch op {
					case "1":
						showGoods()
						flag = true
					case "2":
						AddToCar(name)
						flag = true
					case "3":
						Checkout(name)
						flag = true
					case "4":
						flag = false
					default:
						fmt.Println("请输入正确的选项！")
						flag = true
					}
				}
				
			} else {
				fmt.Println("用户名或密码错误，请重试")
			}
		case "2":
			var name string
			var passwd string
			fmt.Print("请输入用户名：")
			fmt.Scan(&name)
			fmt.Print("请输入密码：")
			fmt.Scan(&passwd)
			if register(name, passwd) {
				fmt.Println("注册成功!")
			}
		case "q":
			 os.Exit(3)
		default:
			fmt.Println("请输入正确的选项!")
		}
	}
}

//从文件中读取信息，初始化user
func init_user(filename string)  {
	content, err := os.ReadFile(filename) //只读方式打开文件
	if err != nil {
		fmt.Println("初始化用户信息失败，没有指定文件！")
	} else {
		err1 := json.Unmarshal(content, &user)
		if err1 != nil{
			fmt.Println("json格式化失败，初始化用户信息失败！")
		}
	}
}

func login(name string, passwd string) bool{
	_, ok := user[name]
	if ok && user[name]["passwd"] == passwd{
		return true
	} else {
		return false
	}
}

func register(name string, passwd string) bool {
	_, ok := user[name]; if ok{
		fmt.Println("用户已存在，请重新输入!")
		return false
	} else {
		var money int
		fmt.Println("请输入您的充值金额：")
		fmt.Scan(&money)
		m := strconv.Itoa(money)
		var name_map = map[string]string{
			"passwd": passwd,
			"money": m,
		}
		user[name] = name_map
		WriteUserInfo()
		_, err := os.ReadFile(shoppingcar_file)
		if err != nil {
			CreateShoppingCar()
		}
		return true
	}
}

func WriteUserInfo() {
	file, err := os.OpenFile(user_file, os.O_CREATE|os.O_WRONLY,666)
	if err != nil{
		fmt.Println("打开文件，写入用户信息失败!")
	} else {
		str_m1, _ := json.Marshal(user)
		file.Write(str_m1)
		fmt.Println("用户信息更新！")
	}
}

func CreateShoppingCar() {
	_, err := os.OpenFile(shoppingcar_file, os.O_CREATE,666)
	if err != nil{
		fmt.Println("打开文件，加载购物车信息失败!")
	} else {
		fmt.Println("成功创建购物车！")
	}
}

func menu() {
	fmt.Println("*****************************")
	fmt.Println("1、查看商品列表")
	fmt.Println("2、添加到购物车")
	fmt.Println("3、结算")
	fmt.Println("4、退出")
}

func showGoods() {
	fmt.Println("*****************************")
	fmt.Printf("|%-10s|%-10s|%-10s|\n","Code", "Item", "Price")
	for k, v := range products{
		fmt.Printf("|%-10s|%-10s|%-10s|\n", k, v["name"], v["price"])
	}
}

func AddToCar(name string) {
	fmt.Println("选择商品编号加入购物车：")
	var code string
	var qty int
	fmt.Scan(&code)
	_, ok := products[code]; if ok{
		fmt.Println("请输入添加数量：")
		fmt.Scan(&qty)
		price := (products[code]["price"])
		p, _ := strconv.Atoi(price)
		expense := qty*p
		q := strconv.Itoa(qty)
		e := strconv.Itoa(expense)
		var car_map = map[string]string{
			"item": products[code]["name"],
			"qty": q,
			"expense": e,
		}
		var car = make(map[string]map[string]string)
		car[name] = car_map
		file, err := os.OpenFile(shoppingcar_file, os.O_APPEND,666)
		if err != nil{
			fmt.Println("加载购物车信息失败")
		} else {
			str_m1, _ := json.Marshal(car)
			file.Write(str_m1)
			file.WriteString("\n")
			fmt.Println("成功添加至购物车！")
		}
	}
}
//购物车信息文件	car={"sc": {"item": "apple", "qty": 3, "expense": qty * price}}
func Checkout(name string)  {
	money,_ := strconv.Atoi(user[name]["money"])
	var expense int
	file, _ :=os.OpenFile(shoppingcar_file, os.O_RDONLY,666)
	reader := bufio.NewReader(file)
	var carlist [] map[string]map[string]string
	var newcarlist [] map[string]map[string]string
	for {
		line, _, err := reader.ReadLine()
		if err == io.EOF {
			break
		}
		var datamap map[string]map[string]string
		err1 := json.Unmarshal(line, &datamap)
		if err1 != nil{
			fmt.Println("反序列化错误", err1)
		}
		carlist = append(carlist, datamap)
	}
	for _, v := range carlist{
		for i, j:= range v{
			if i == name {
				e, _ := strconv.Atoi(j["expense"])
				expense += e
			} else {
				newcarlist = append(newcarlist, v)
			}
		}
	}
	os.Truncate(shoppingcar_file, 0)
	file, _ =os.OpenFile(shoppingcar_file, os.O_APPEND,666)
	for _, v := range newcarlist {
		str_m1, _ := json.Marshal(v)
		file.Write(str_m1)
		file.WriteString("\n")
	}
	balance := money - expense
	b := strconv.Itoa(balance)
	user[name]["money"] = b
	WriteUserInfo()
	fmt.Println("本次消费", expense, "元，剩余", balance, "元。欢迎下次光临！")
}